package com.rs.recruit.util;

import java.io.IOException;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.jsp.PageContext;

import com.jspsmart.upload.File;
import com.jspsmart.upload.Files;
import com.jspsmart.upload.Request;
import com.jspsmart.upload.SmartUpload;
import com.jspsmart.upload.SmartUploadException;

/**
 * 文件上传的工具类
 * company 源辰信息
 * @author 梦凝哲雪
 * @date 2099年12月31日
 * @version 1.0
 * Email 1198865589@qq.com
 */
public class FileUploadUtil {
	
	// 注意: 如果上传的类型或文件大小不匹配 将会报各种异常信息  此时 请及时检查常量值中是否书写错误  -> 字母 |空格 
	public static String uploadPath = "../images"; // 默认的上传路径
	public static final String ALLOWEDFILESLIST = "gif,jpeg,png,jpg"; // 允许上传的文件类型
	public static final String DENIEDFILESLIST = "exe,bat,jsp";// 不允许上传的文件类型
	public static final long TOTALMAXFILESIZE = 100 * 1024 * 1024;// 所有上传文件的最大值
	public static final long MAXFILESIZE = 10 * 1024 * 1024;// 单个文件上传的最大值
	
	// 普通文本信息 -> 单文件上传 -> 多文件上传 -> 多文件域  + 多个文件上传
	public Map<String, String> uploads( PageContext pageContext) throws 
			ServletException, IOException, SmartUploadException, SQLException{
		// 存储上传的数据
		Map<String, String>  map = new HashMap<String, String>();
		
		// 上传工具
		SmartUpload su = new SmartUpload();
		// 初始化组件
		su.initialize(pageContext);
		
		// 配置上传相关参数 
		su.setAllowedFilesList( ALLOWEDFILESLIST );// 允许上传的文件类型
		su.setDeniedFilesList( DENIEDFILESLIST ); // 不允许上传的文件类型
		su.setTotalMaxFileSize(TOTALMAXFILESIZE); // 所有上传文件的最大值 
		su.setMaxFileSize( MAXFILESIZE ); // 单个文件上传的最大值
		su.setCharset("UTF-8"); // 设置编码集
		
		su.upload(); // 文件上传
		
		// 获取请求中上传的普通文本i西南西  非文件信息
		// 注释： 此时的request 式com.jspsmart.upload.Request 而不是 HttpServletRequest
		Request request = su.getRequest();
		
		// 获取请求中的参数对应的表单元素的控件名字  name属性的值
		Enumeration<String>  enumers = request.getParameterNames();
		// 表单元素的控件名字  name 来获取对应参数值
		String name = null;
		// 循环枚举
		while (enumers.hasMoreElements()) {
			name = (String) enumers.nextElement(); // 键
			map.put( name, request.getParameter(name));// 值 
		}
		// return map; // 此时只是 上传的普通文本信息
		
		/*思考问题
		1、如何上传文件 
		2、文件存在服务器的哪个位置
		3、文件如何写入到指定的位置
		4、获取存储后的文件路径  如何处理 存储到image_path 
		5、如果服务器指定位置 有 多张相同名称图片 又如何处理	*/
		
		Files files = su.getFiles();// 获取所有的上传文件信息
		// 如果无文件上传  就直接返回普通文本信息
		if( files == null || files.getCount() <=0 || files.getSize() <= 0) {
			return map; // 此时只是 上传的普通文本信息
		}
		// 意味有文件上传 则循环取出 用户上传的文件
		Collection<File> fls = files.getCollection();
		
		// TODO   获取上传的服务器绝对路径 -> Tomcat的安装路径 -> D:\softwares\Tomcat\apache-tomcat-9.0.64\webapps\项目名\
		// String basePath = pageContext.getRequest().getRealPath("/"); // D:\softwares\Tomcat\apache-tomcat-9.0.64\webapps\goods\
		String basePath = pageContext.getServletContext().getRealPath("/"); // 对应的实例名 JSP内置对象 application 
		System.out.println( basePath ); // D:\softwares\Tomcat\apache-tomcat-9.0.64\webapps\goods\
		
		String fieldName = null;// 上传的控件名称 
		String fileName = null;// 上传的文件名  相对路径 
		String filePath = null;// 文件保存的路径  绝对路径
		
		// 多文件 多文件域
		String pathStr = null;// 多图路径   1.png;2.png
		String temp = null;// 多文件域(网页上传控件名) 的  控件名称 
		
		// 循环取出文件
		for (File file : fls) {
			if( !file.isMissing() ) {  //  文件为丢失的情况下 进行文件存储
				// 控件名   文件名  文件路径
				System.out.println( file.getFieldName() + "--" + file.getFileName() + "--" + file.getFilePathName());
				
				temp = file.getFieldName(); // 控件名  g_image  photo 
				if( StringUtil.checkNull( fieldName )) { // 如何这个变量是空的 意味着  第一个文件域 要上传的文件 
					fieldName = temp;
				}else { // 否则就是其他文件域
					if( !temp.equals(  fieldName )) { // 不同域上传
						map.put(fieldName, pathStr); // 首先存储 第一个文件域中的所有多图路径  
						pathStr = ""; // 清空多图路径 准备存储下一个文件域 多图路径 
						fieldName = temp;
					}
				}
				
				// 为了避免用户上传 相同的文件名的文件  自定义文件名  时间戳 + fileName ->  fieldName  fileName
				fieldName = file.getFieldName();
				fileName = uploadPath + "/" + new Date().getTime() + "_" + file.getFileName(); // images/123_yc.png
				// 将上传的文件存储到服务器的指定目录  获取上传的服务器路径 + 自定义的文件名
				filePath =  basePath + fileName;
				System.out.println( filePath );// D:\softwares\Tomcat\apache-tomcat-9.0.64\webapps\goods\images/123_yc.png
				// D:\softwares\Tomcat\apache-tomcat-9.0.64\webapps\goods\images/1657111454146_事件处理机制分析.png
				
				// 现象保存服务器项目目录下的images文件夹下  不能永久化存储文件信息  图片在服务器更新并重启后消失  
				
				// TODO 如何持久化存储 文件信息   uploadPath = "../images" 加上上一级目录 与 项目目录平级  
				// D:\softwares\Tomcat\apache-tomcat-9.0.64\webapps\goods\images/1657111454146_事件处理机制分析.png
				
				// D:\softwares\Tomcat\apache-tomcat-9.0.64\webapps\goods\../images/1657111454146_事件处理机制分析.png
				// D:\softwares\Tomcat\apache-tomcat-9.0.64\webapps\images/1657111454146_事件处理机制分析.png
				
				// TODO 1、如果是一个文件域中多个文件 如何处理？ --> 提示： 字符串拼接  1.png;2.png  1->n
				// TODO 2、如果是多文件域 每一个文件也可能出现多个文件 又该如何处理？ n -> n
				
				// 判断是否是多图上图 
				if( StringUtil.checkNull( pathStr )) {
					pathStr = fileName;// 当前文件域的第一张图片 				
				} else {
					pathStr += ";" + fileName;// 后续的图片 
				}
				
				// 开始存储上传文件信息
				file.saveAs( filePath, SmartUpload.SAVE_PHYSICAL);
			}
		} 
		// map.put( fieldName, fileName); // 存储上传的文件信息 控件名 -> 单个自定义文件相对路径存入map
		
		map.put( fieldName, pathStr); // 存储上传的文件信息 控件名 -> 单个自定义文件相对路径存入map -> 多图路径  ../images/123_yc.png;../images/456_yc.png
		return map; // 返回最终的信息 
		
		// TODO 以对象的方式封装前端传递过来的请求参数  自定义  -> ORM  持久性框架   
	}
	
	
	// 富文本单图片上传
	public Map<String, String> upload(PageContext pageContext) throws Exception{
		Map<String, String> map = new HashMap<String, String>();
		SmartUpload su = new SmartUpload();
		// 初始组件
		su.initialize(pageContext);
		// 设置参数
		su.setAllowedFilesList(ALLOWEDFILESLIST);// 允许上传的文件类型
		su.setDeniedFilesList(DENIEDFILESLIST);// 不允许上传的文件类型
		su.setTotalMaxFileSize(MAXFILESIZE);// 单个上传文件的最大值
		su.setMaxFileSize(TOTALMAXFILESIZE);// 最大总上传文件的最大值
		su.setCharset("UTF-8");// 上传数据的编码集
		su.upload();// 开始上传
		// TODO  处理上传文件 
		Files files = su.getFiles(); // 获取所有的文件
		// 如果无文件 就直接 普通文本信息    说明用户未上传文件
		if( files == null || files.getCount() <= 0 || files.getSize() <= 0 || files.getFile(0).getSize() <= 0 ) {
			return map;// 此时获取所有的普通文本信息
		}
		
		// 有 则循环取出用户上传的文件
		Collection<File> fls = files.getCollection();
		
		// 获取保存文件的文件夹的绝对路径 -> Tomcat服务器的绝对路径   C...\webapps\项目名\
		String basePath = pageContext.getServletContext().getRealPath("/");
				
		String fileName = null;// 上传后的文件名称
	    String fieldName = null;// 上传文件域的控件name属性
		String filePath = null;// 文件保存的路径		
			
		// 循环处理 文件 
		for(File fl : fls) {
			if( !fl.isMissing()) { // 文件未丢失 打印相关信息
				// 为了避免 文件名相同出现的文件覆盖问题  所以自定义上传文件的名称   注意   fileName  fieldName
				fieldName = fl.getFieldName();
				fileName = uploadPath + "/" + new Date().getTime() + "_" + fl.getFileName();// images/123_head19.jpg 
	
				// 将上传的文件存储到服务器的指定目录    获取上传的服务器路径 + 自定义路径 + 自定义名称   
				filePath =  basePath + fileName;  // 绝对路径 存储文件
				
				// 开始存储文件
				fl.saveAs(filePath, SmartUpload.SAVE_PHYSICAL); 
			}
		}
		map.put(fieldName, fileName);// 富文本上传的控件
		return map;
	}
}
